Re: A quick patch to help against TCP ISN guessing.

Darren Reed (avalon@coombs.anu.edu.au)
Tue, 24 Jan 1995 22:46:26 +1100 (EDT)

Ermmm, that patch was rather lame (forget it, /dev/null it)...almost
as if I'd ignored what I'd read this afternoon :-/  Anyway, after some
pizza and some coke I soon woke up to a silly error on my behalf.  The
"FASTER" bit was just another incarnation of the silly `BSD' code.
(ps. to those who were wondering how to tell a real consultant from the
fakes, take them out to lunch or dinner and see what they eat :-)
This more reflects what is suggested, where tcp_iss is incremented by a
variable amount each time, which although `random', still doesn't clock
itself inside 4*MSL.

This isn't much better, tcp_iss changes 10 times a second, plus once per
connection, as against 2 plus extras.  Ideally it would change off its own
clock driven counter, but doing this is harder and I'll leave that to the
vendors who I trust are working on better ways to fix this "problem" and
will have real patches out in the next week or so.  (Anyone else feeling
as optimistic as me ?)

But still, make sure your routers block packets which claim to be from you
but are heading for your network!  This should be among the first rules
added to any IP packet filter which is part of a firewall!  (Even I didn't
have them till a few hours ago :-/)

Cheers,
Darren

(if that other email was a newspost, I'd have cancelled it, sorry, time
 to go and hide for a while I think).

*** /sys/netinet/in_proto.c.orig	Fri Oct 14 06:45:48 1994
--- /sys/netinet/in_proto.c	Tue Jan 24 22:20:45 1995
***************
*** 21,26 ****
--- 21,27 ----
  #include <netinet/in.h>
  #include <netinet/in_systm.h>
  #include <netinet/tcp_timer.h>
+ #include <netinet/tcp.h>
  
  /*
   * TCP/IP protocol family: IP, ICMP, UDP, TCP.
***************
*** 35,40 ****
--- 36,42 ----
  int	tcp_usrreq(),tcp_ctloutput();
  int	tcp_init(),tcp_fasttimo(),tcp_slowtimo(),tcp_drain();
  int	rip_input(),rip_output(),rip_ctloutput();
+ int	rand_tcp_slowtimer(), rand_tcp_fasttimo(), rand_tcp_init();
  extern	int raw_usrreq();
  
  #ifdef NSIP
***************
*** 57,63 ****
  { SOCK_STREAM,	&inetdomain,	IPPROTO_TCP,	PR_CONNREQUIRED|PR_WANTRCVD,
    tcp_input,	0,		tcp_ctlinput,	tcp_ctloutput,
    tcp_usrreq,
!   tcp_init,	tcp_fasttimo,	tcp_slowtimo,	tcp_drain,
  },
  { SOCK_RAW,	&inetdomain,	IPPROTO_RAW,	PR_ATOMIC|PR_ADDR,
    rip_input,	rip_output,	0,		rip_ctloutput,
--- 59,65 ----
  { SOCK_STREAM,	&inetdomain,	IPPROTO_TCP,	PR_CONNREQUIRED|PR_WANTRCVD,
    tcp_input,	0,		tcp_ctlinput,	tcp_ctloutput,
    tcp_usrreq,
!   rand_tcp_init,	rand_tcp_fasttimo,	rand_tcp_slowtimer,	tcp_drain,
  },
  { SOCK_RAW,	&inetdomain,	IPPROTO_RAW,	PR_ATOMIC|PR_ADDR,
    rip_input,	rip_output,	0,		rip_ctloutput,
***************
*** 148,150 ****
--- 150,239 ----
  int	udp_sendspace = 9000;		/* really max datagram size */
  int	udp_recvspace = 2*(9000+sizeof(struct sockaddr)); /* 2 8K dgrams */
  
+ /*
+  * This is designed to introduce some randomness into the TCP sequence
+  * numbers.
+  * - Darren Reed 24/1/95 (darrenr@arbld.unimelb.edu.au)
+  */
+ extern	tcp_seq	tcp_iss;
+ 
+ #define	FASTER_ISN
+ #undef	RANDOM_ISN
+ #ifndef	TCP_COMPAT_42
+ #define	TCP_COMPAT_42		/* better defined than not */
+ #endif
+ /*
+  * Make initial choice more random.
+  */
+ rand_tcp_init()
+ {
+ 	int	r = tcp_init();
+ 	unsigned long ul[2];
+ 
+ 	uniqtime(ul);
+ 	tcp_iss = ul[0] * ul[1];
+ 	if (tcp_iss < 0)
+ 		tcp_iss = -tcp_iss;
+ 	return r;
+ }
+ 
+ 
+ /*
+  * Get this 2 times a second (PR_SLOWHZ)
+  */
+ rand_tcp_slowtimer()
+ {
+ 	int	s = splnet(), r;
+ 	unsigned long ul[2];
+ 
+ 	r = tcp_slowtimo();
+ 	/*
+ 	 * we should still be at splnet()
+ 	 */
+ 	uniqtime(ul);
+ #ifdef	RANDOM_ISN
+ 	if (!tcp_iss)
+ 		tcp_iss = ul[0] * 16381;
+ 	tcp_iss += ul[1];
+ #else
+ # ifdef	FASTER_ISN
+ 	tcp_iss += (ul[0] ^ ul[1]) & 0x3fffff;
+ # endif
+ #endif
+ #ifdef	TCP_COMPAT_42
+ 	if (tcp_iss < 0)
+ 		tcp_iss = -tcp_iss;
+ 	else if (!tcp_iss)
+ 		tcp_iss = ul[1] ^ 0xa5a5a5;
+ #endif
+ 	splx(s);
+ 	return r;
+ }
+ 
+ 
+ /*
+  * Get this 5 times a second (PR_FASTHZ)
+  */
+ rand_tcp_fasttimo()
+ {
+ 	int	s = splnet(), r;
+ 	unsigned long	ul[2];
+ 
+ 	uniqtime(ul);
+ #ifdef	RANDOM_ISN
+ 	tcp_iss *= 32749;
+ #else
+ # ifdef	FASTER_ISN
+ 	tcp_iss += (ul[0] ^ ul[1]) & 0x7ff;
+ # endif
+ #endif
+ #ifdef	TCP_COMPAT_42
+ 	if (tcp_iss < 0)
+ 		tcp_iss = -tcp_iss;
+ 	else if (!tcp_iss)
+ 		tcp_iss = ul[1] ^ 0xa5a5a5;
+ #endif
+ 	r = tcp_fasttimo();
+ 	splx(s);
+ 	return r;
+ }